package jwcb.admin.server.user.service.impl;

import cn.hutool.crypto.digest.DigestUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import jwcb.admin.server.dictionary.service.ISysDictionaryService;
import jwcb.admin.server.user.domain.dto.*;
import jwcb.admin.server.user.domain.entity.SysUser;
import jwcb.admin.server.user.mapper.SysUserMapper;
import jwcb.admin.server.user.service.ISysUserService;
import jwcb.javapjframework.common.core.enums.UserFrom;
import jwcb.javapjframework.common.core.enums.UserIdentity;
import jwcb.javapjframework.common.core.enums.UserStatus;
import jwcb.javapjframework.common.core.utils.*;
import jwcb.javapjframework.common.domain.constants.SecurityConstants;
import jwcb.javapjframework.common.domain.domain.ResultCode;
import jwcb.javapjframework.common.domain.exception.ServiceException;
import jwcb.javapjframework.common.domain.domain.dto.LoginUserDto;
import jwcb.javapjframework.common.security.domain.dto.TokenDto;
import jwcb.javapjframework.common.security.service.TokenService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * B端用户服务层实现类
 */
@Service
public class ISysUserServiceImpl implements ISysUserService {


    @Autowired
    private ISysDictionaryService sysDictionaryService;
    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private TokenService tokenService;

    /**
     * B端用户登录
     * @param passwordLoginDto 账号密码信息
     * @return token信息
     */
    @Override
    public TokenDto login(PasswordLoginDto passwordLoginDto) {
        if(!VerifyUtil.checkPhone(passwordLoginDto.getPhoneNumber())) {
            throw new ServiceException(ResultCode.ERROR_PHONE_FORMAT);
        }
        SysUser sysUser = sysUserMapper.selectOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getPhoneNumber, AESUtil.encryptHex(passwordLoginDto.getPhoneNumber())));
        if(sysUser == null) {
            throw new ServiceException("手机号未注册",ResultCode.INVALID_PARA.getCode());
        }
        // 先解密密码(密文传输)
        String password = AESUtil.decryptHex(passwordLoginDto.getPassword());
        if(StringUtil.isEmpty(password)) {
            throw new ServiceException("密码无效",ResultCode.INVALID_PARA.getCode());
        }
        // 校验密码正确性
        String encryptedPassword = DigestUtil.sha256Hex(password);
        if(!encryptedPassword.equals(sysUser.getPassword())) {
            throw new ServiceException("密码校验失败",ResultCode.INVALID_PARA.getCode());
        }
        // 校验用户状态
        if(UserStatus.DISABLE.getDesc().equals(sysUser.getStatus())) {
            throw new ServiceException(ResultCode.USER_DISABLE);
        }
        LoginUserDto loginUserDto = new LoginUserDto();
        loginUserDto.setUserId(sysUser.getId());
        loginUserDto.setUserName(sysUser.getNickName());
        loginUserDto.setUserFrom(UserFrom.SYS_USER.getDesc());
        loginUserDto.setUserIdentity(sysUser.getIdentity());
        return tokenService.createToken(loginUserDto);
    }


    /**
     * 新增用户信息
     * @param sysUserAddDto B端用户信息DTO
     * @return 用户Id
     */
    @Override
    public Long add(SysUserAddDto sysUserAddDto) {
        // 检查当前用户的操作权限
        Integer currentUserIdentity = ThreadLocalUtil.get(SecurityConstants.USER_IDENTITY,Integer.class);
        if(!UserIdentity.SUPER_ADMIN.getValue().equals(currentUserIdentity)) {
            throw new ServiceException(ResultCode.NOT_PERMISSION);
        }
        // 用户唯一性校验
        SysUser sysUser = sysUserMapper.selectOne(new LambdaQueryWrapper<SysUser>()
                .eq(SysUser::getPhoneNumber, AESUtil.encryptHex(sysUserAddDto.getPhoneNumber())));
        if(sysUser != null) {
            throw new ServiceException(ResultCode.PHONE_ALREADY_REGISTER);
        }
        String password = AESUtil.decryptHex(sysUserAddDto.getPassword());
        if(!checkUserPassword(password)) {
            throw new ServiceException(ResultCode.PASSWORD_FORMAT_INVALID);
        }
        // 新增用户
        sysUser = new SysUser();
        sysUser.setPhoneNumber(AESUtil.encryptHex(sysUserAddDto.getPhoneNumber()));
        sysUser.setNickName(sysUserAddDto.getNickName());
        sysUser.setPassword(DigestUtil.sha256Hex(password));
        sysUser.setRemark(sysUserAddDto.getRemark());
        sysUser.setIdentity(sysUserAddDto.getIdentity());
        sysUser.setStatus(sysUserAddDto.getStatus());
        sysUserMapper.insert(sysUser);
        return sysUser.getId();
    }


    /**
     * 编辑用户信息
     * @param sysUserEditDto B端用户信息DTO
     * @return 用户Id
     */
    @Override
    public Long edit(SysUserEditDto sysUserEditDto) {
        // 检查当前用户的操作权限
        Integer currentUserIdentity = ThreadLocalUtil.get(SecurityConstants.USER_IDENTITY,Integer.class);
        Long currentUserId = ThreadLocalUtil.get(SecurityConstants.USER_ID,Long.class);
        if(!UserIdentity.SUPER_ADMIN.getValue().equals(currentUserIdentity)
        && !Objects.equals(sysUserEditDto.getUserId(), currentUserId)) {
            // 权限不足或不允许普通管理员操作
            throw new ServiceException(ResultCode.NOT_PERMISSION);
        }
        // 不允许禁用自己
        if(Objects.equals(sysUserEditDto.getUserId(), currentUserId) &&  UserStatus.DISABLE.getValue().equals(sysUserEditDto.getStatus())) {
            throw new ServiceException(ResultCode.CANT_FORBIDDEN_SELF);
        }
        // 用户是否存在
        SysUser sysUser = sysUserMapper.selectOne(new LambdaQueryWrapper<SysUser>()
                .eq(SysUser::getId, sysUserEditDto.getUserId()));
        if(sysUser == null) {
            throw new ServiceException(ResultCode.USER_NOT_EXIST);
        }

        String password = AESUtil.decryptHex(sysUserEditDto.getPassword());
        if(password != null && !checkUserPassword(password)) {
            throw new ServiceException(ResultCode.PASSWORD_FORMAT_INVALID);
        }
        sysUser.setIdentity(sysUserEditDto.getIdentity());
        sysUser.setNickName(sysUserEditDto.getNickName());
        if(sysUserEditDto.getPassword() != null) {
            sysUser.setPassword(DigestUtil.sha256Hex(password));
        }
        sysUser.setStatus(sysUserEditDto.getStatus());
        sysUser.setRemark(sysUserEditDto.getRemark());
        sysUserMapper.updateById(sysUser);
        return sysUser.getId();
    }



    /**
     * 查询B端用户
     * @param sysUserListReqDTO 用户查询DTO
     * @return B用户列表
     */
    @Override
    public List<SysUserDTO> getUserList(SysUserListReqDTO sysUserListReqDTO) {
        List<SysUser> sysUsers = sysUserMapper.selectList(new LambdaQueryWrapper<SysUser>()
                .eq(sysUserListReqDTO.getUserId() != null, SysUser::getId, sysUserListReqDTO.getUserId())
                .eq(StringUtil.isNoneBlank(sysUserListReqDTO.getPhoneNum()), SysUser::getPhoneNumber, AESUtil.encryptHex(sysUserListReqDTO.getPhoneNum()))
                .eq(sysUserListReqDTO.getStatus() != null, SysUser::getStatus, sysUserListReqDTO.getStatus()));
        List<SysUserDTO> sysUserDTOS = new ArrayList<>();
        for(SysUser sysUser : sysUsers) {
            SysUserDTO sysUserDTO = new SysUserDTO();
            BeanCopyUtil.copyProperties(sysUser,sysUserDTO);
            sysUserDTO.setPhoneNumber(AESUtil.decryptHex(sysUserDTO.getPhoneNumber()));
            sysUserDTOS.add(sysUserDTO);
        }
        return sysUserDTOS;
    }



    /**
     * 获取B端登录用户信息
     * @return B端用户信息VO
     */
    @Override
    public SysUserLoginDto getLoginUser() {
        LoginUserDto loginUserDto = tokenService.getLoginUserDto();
        if(loginUserDto == null || loginUserDto.getUserId() == null) {
            throw new ServiceException(ResultCode.TOKEN_INVALID);
        }
        SysUser sysUser = sysUserMapper.selectById(loginUserDto.getUserId());
        if(sysUser == null) {
            throw new ServiceException(ResultCode.USER_NOT_EXIST);
        }
        SysUserLoginDto sysUserLoginDto = new SysUserLoginDto();
        BeanCopyUtil.copyProperties(loginUserDto,sysUserLoginDto);
        BeanCopyUtil.copyProperties(sysUser,sysUserLoginDto);
        return sysUserLoginDto;
    }

    /**
     * 密码
     * @return 是否合规 (至少存在数字和英文字母,8-16位)
     */
    private boolean checkUserPassword(String aesPassword) {
        return aesPassword.matches("^(?=.*[A-Za-z])(?=.*\\d).{8,16}$");
    }

}
